package ru.myrtle.umf.tools.ugen.templates;

import java.io.*;
import java.text.*;
import java.util.*;
import ru.myrtle.umf.*;
import ru.myrtle.umf.codegen.*;
import ru.myrtle.umf.codegen.java.*;
import ru.myrtle.umf.tools.ugen.*;

public class UObjectOpStubTemplate extends UTemplate
{
    protected final String NL = System.getProperties().getProperty("line.separator");
    protected final String TEXT_1 = "package ";
    protected final String TEXT_2 = ";" + NL + NL + "public abstract class ";
    protected final String TEXT_3 = " {" + NL + NL + "    public static final ";
    protected final String TEXT_4 = " INSTANCE = new ";
    protected final String TEXT_5 = "();" + NL + NL;
    protected final String TEXT_6 = "    public abstract ";
    protected final String TEXT_7 = " ";
    protected final String TEXT_8 = "(";
    protected final String TEXT_9 = " self);" + NL + NL + "    public abstract boolean ";
    protected final String TEXT_10 = "(";
    protected final String TEXT_11 = " self);" + NL + NL;
    protected final String TEXT_12 = "    public ";
    protected final String TEXT_13 = " ";
    protected final String TEXT_14 = "(";
    protected final String TEXT_15 = " self) {" + NL + "        return ";
    protected final String TEXT_16 = ".INSTANCE.";
    protected final String TEXT_17 = "(self);" + NL + "    }" + NL + "    " + NL + "    public boolean ";
    protected final String TEXT_18 = "(";
    protected final String TEXT_19 = " self) {" + NL + "        return ";
    protected final String TEXT_20 = ".INSTANCE.";
    protected final String TEXT_21 = "(self);" + NL + "    }" + NL + NL;
    protected final String TEXT_22 = "    public abstract void ";
    protected final String TEXT_23 = "(";
    protected final String TEXT_24 = " self, ";
    protected final String TEXT_25 = " ";
    protected final String TEXT_26 = ");" + NL + NL + "    public abstract void ";
    protected final String TEXT_27 = "(";
    protected final String TEXT_28 = " self);" + NL + NL;
    protected final String TEXT_29 = "    public void ";
    protected final String TEXT_30 = "(";
    protected final String TEXT_31 = " self, ";
    protected final String TEXT_32 = " ";
    protected final String TEXT_33 = ") {" + NL + "        ";
    protected final String TEXT_34 = ".INSTANCE.";
    protected final String TEXT_35 = "(self, ";
    protected final String TEXT_36 = ");" + NL + "    }" + NL + NL + "    public void ";
    protected final String TEXT_37 = "(";
    protected final String TEXT_38 = " self) {" + NL + "        ";
    protected final String TEXT_39 = ".INSTANCE.";
    protected final String TEXT_40 = "(self);" + NL + "    }" + NL + NL;
    protected final String TEXT_41 = "    public abstract ";
    protected final String TEXT_42 = " ";
    protected final String TEXT_43 = "(";
    protected final String TEXT_44 = " self);" + NL + NL + "    public abstract boolean ";
    protected final String TEXT_45 = "(";
    protected final String TEXT_46 = " self);" + NL + NL;
    protected final String TEXT_47 = "    public ";
    protected final String TEXT_48 = " ";
    protected final String TEXT_49 = "(";
    protected final String TEXT_50 = " self) {" + NL + "        return ";
    protected final String TEXT_51 = ".INSTANCE.";
    protected final String TEXT_52 = "(self);" + NL + "    }" + NL + NL + "    public boolean ";
    protected final String TEXT_53 = "(";
    protected final String TEXT_54 = " self) {" + NL + "        return ";
    protected final String TEXT_55 = ".INSTANCE.";
    protected final String TEXT_56 = "(self);" + NL + "    }" + NL + NL;
    protected final String TEXT_57 = "    public abstract void ";
    protected final String TEXT_58 = "(";
    protected final String TEXT_59 = " self, ";
    protected final String TEXT_60 = " ";
    protected final String TEXT_61 = ");" + NL + NL + "    public abstract void ";
    protected final String TEXT_62 = "(";
    protected final String TEXT_63 = " self);" + NL + NL;
    protected final String TEXT_64 = "    public void ";
    protected final String TEXT_65 = "(";
    protected final String TEXT_66 = " self, ";
    protected final String TEXT_67 = " ";
    protected final String TEXT_68 = ") {" + NL + "        ";
    protected final String TEXT_69 = ".INSTANCE.";
    protected final String TEXT_70 = "(self, ";
    protected final String TEXT_71 = ");" + NL + "    }" + NL + NL + "    public void ";
    protected final String TEXT_72 = "(";
    protected final String TEXT_73 = " self) {" + NL + "        ";
    protected final String TEXT_74 = ".INSTANCE.";
    protected final String TEXT_75 = "(self);" + NL + "    }" + NL + NL;
    protected final String TEXT_76 = "    ";
    protected final String TEXT_77 = ";" + NL + "    " + NL;
    protected final String TEXT_78 = "    ";
    protected final String TEXT_79 = " {" + NL + "        ";
    protected final String TEXT_80 = ".INSTANCE.";
    protected final String TEXT_81 = "(";
    protected final String TEXT_82 = ");" + NL + "    }" + NL + NL;
    protected final String TEXT_83 = "}" + NL;
    protected final String TEXT_84 = NL;

    /*
     *
     */


    public UObjectOpStubTemplate() {

    }

    /*
     *
     */

    public String generate(UTemplateContext context) throws UTemplateRejectException
    {
        final StringBuffer stringBuffer = new StringBuffer();

    checkTemplateObjectType(context, UClass.class);

    UClass object = (UClass) context.getObject();

    if (!UGenUtil.hasDerivedFeatures(object) && !UGenUtil.hasNotProvidedOperations(object)) {
        reject();
    }

    String opClassName     = UGenUtil.getObjectOpClassName(object);
    String opClassPackage  = UGenUtil.getObjectOpClassPackage(object);

    String opStubClassName    = UGenUtil.getObjectOpStubClassName(object);
    String opStubClassPackage = UGenUtil.getObjectOpStubClassPackage(object);

    context.getResource().setObjectFileName(opStubClassName);
    context.getResource().setObjectFileExtension("java");
    context.getResource().setObjectPackage(opStubClassPackage);

    JavaImportBuilder importBuilder = new JavaImportBuilder();

    importBuilder.addPackage("java.util");
    importBuilder.addPackage("ru.myrtle.umf");
    importBuilder.addPackage("ru.myrtle.umf.util");
    importBuilder.addPackage(opClassPackage);

        stringBuffer.append(TEXT_1);
        stringBuffer.append(opStubClassPackage);
        stringBuffer.append(TEXT_2);
        stringBuffer.append(opStubClassName);
        stringBuffer.append(TEXT_3);
        stringBuffer.append(opClassName);
        stringBuffer.append(TEXT_4);
        stringBuffer.append(opClassName);
        stringBuffer.append(TEXT_5);

    String selfType = UGenUtil.getInstanceTypeName(
        object, importBuilder
    );

    for (UFeature feature : object.getAllFeatures()) {
        if (feature.isDerived()) {
            if (feature instanceof UAttribute) {
                UAttribute attribute = (UAttribute) feature;

                String attributeName = attribute.getName();
                String attributeType = UGenUtil.getInstanceTypeName(
                    attribute, importBuilder
                );

                String varName = "_" + attributeName + "_";

                String getOpName   = UGenUtil.getAccessorPrefix(attribute) + UGenUtil.capName(attributeName);
                String isSetOpName = "isSet" + UGenUtil.capName(attributeName);

                if (object == feature.getContainingClass()) {

        stringBuffer.append(TEXT_6);
        stringBuffer.append(attributeType);
        stringBuffer.append(TEXT_7);
        stringBuffer.append(getOpName);
        stringBuffer.append(TEXT_8);
        stringBuffer.append(selfType);
        stringBuffer.append(TEXT_9);
        stringBuffer.append(isSetOpName);
        stringBuffer.append(TEXT_10);
        stringBuffer.append(selfType);
        stringBuffer.append(TEXT_11);

                }
                else {
                    String owningOpClassName = UGenUtil.getObjectOpClassName(
                        feature.getContainingClass()
                    );

        stringBuffer.append(TEXT_12);
        stringBuffer.append(attributeType);
        stringBuffer.append(TEXT_13);
        stringBuffer.append(getOpName);
        stringBuffer.append(TEXT_14);
        stringBuffer.append(selfType);
        stringBuffer.append(TEXT_15);
        stringBuffer.append(owningOpClassName);
        stringBuffer.append(TEXT_16);
        stringBuffer.append(getOpName);
        stringBuffer.append(TEXT_17);
        stringBuffer.append(isSetOpName);
        stringBuffer.append(TEXT_18);
        stringBuffer.append(selfType);
        stringBuffer.append(TEXT_19);
        stringBuffer.append(owningOpClassName);
        stringBuffer.append(TEXT_20);
        stringBuffer.append(isSetOpName);
        stringBuffer.append(TEXT_21);

                }

                if (attribute.isChangeable()) {
                    String setOpName    = "set" + UGenUtil.capName(attributeName);
                    String unsetOpName  = "unset" + UGenUtil.capName(attributeName);

                    if (object == feature.getContainingClass()) {

        stringBuffer.append(TEXT_22);
        stringBuffer.append(setOpName);
        stringBuffer.append(TEXT_23);
        stringBuffer.append(selfType);
        stringBuffer.append(TEXT_24);
        stringBuffer.append(attributeType);
        stringBuffer.append(TEXT_25);
        stringBuffer.append(varName);
        stringBuffer.append(TEXT_26);
        stringBuffer.append(unsetOpName);
        stringBuffer.append(TEXT_27);
        stringBuffer.append(selfType);
        stringBuffer.append(TEXT_28);

                    }
                    else {
                        String owningOpClassName = UGenUtil.getObjectOpClassName(
                            feature.getContainingClass()
                        );

        stringBuffer.append(TEXT_29);
        stringBuffer.append(setOpName);
        stringBuffer.append(TEXT_30);
        stringBuffer.append(selfType);
        stringBuffer.append(TEXT_31);
        stringBuffer.append(attributeType);
        stringBuffer.append(TEXT_32);
        stringBuffer.append(varName);
        stringBuffer.append(TEXT_33);
        stringBuffer.append(owningOpClassName);
        stringBuffer.append(TEXT_34);
        stringBuffer.append(setOpName);
        stringBuffer.append(TEXT_35);
        stringBuffer.append(varName);
        stringBuffer.append(TEXT_36);
        stringBuffer.append(unsetOpName);
        stringBuffer.append(TEXT_37);
        stringBuffer.append(selfType);
        stringBuffer.append(TEXT_38);
        stringBuffer.append(owningOpClassName);
        stringBuffer.append(TEXT_39);
        stringBuffer.append(unsetOpName);
        stringBuffer.append(TEXT_40);

                    }
                }
            }
            else if (feature instanceof UReference) {
                UReference reference = (UReference) feature;

                String referenceName = reference.getName();
                String referenceType = UGenUtil.getInstanceTypeName(
                    reference, importBuilder
                );

                String varName = "_" + referenceName + "_";

                String getOpName    = "get" + UGenUtil.capName(referenceName);
                String isSetOpName  = "isSet" + UGenUtil.capName(referenceName);

                if (object == feature.getContainingClass()) {

        stringBuffer.append(TEXT_41);
        stringBuffer.append(referenceType);
        stringBuffer.append(TEXT_42);
        stringBuffer.append(getOpName);
        stringBuffer.append(TEXT_43);
        stringBuffer.append(selfType);
        stringBuffer.append(TEXT_44);
        stringBuffer.append(isSetOpName);
        stringBuffer.append(TEXT_45);
        stringBuffer.append(selfType);
        stringBuffer.append(TEXT_46);

                }
                else {
                    String owningOpClassName = UGenUtil.getObjectOpClassName(
                        feature.getContainingClass()
                    );

        stringBuffer.append(TEXT_47);
        stringBuffer.append(referenceType);
        stringBuffer.append(TEXT_48);
        stringBuffer.append(getOpName);
        stringBuffer.append(TEXT_49);
        stringBuffer.append(selfType);
        stringBuffer.append(TEXT_50);
        stringBuffer.append(owningOpClassName);
        stringBuffer.append(TEXT_51);
        stringBuffer.append(getOpName);
        stringBuffer.append(TEXT_52);
        stringBuffer.append(isSetOpName);
        stringBuffer.append(TEXT_53);
        stringBuffer.append(selfType);
        stringBuffer.append(TEXT_54);
        stringBuffer.append(owningOpClassName);
        stringBuffer.append(TEXT_55);
        stringBuffer.append(isSetOpName);
        stringBuffer.append(TEXT_56);

                }

                if (reference.isChangeable()) {
                    String setOpName    = "set" + UGenUtil.capName(referenceName);
                    String unsetOpName  = "unset" + UGenUtil.capName(referenceName);

                    if (object == feature.getContainingClass()) {


        stringBuffer.append(TEXT_57);
        stringBuffer.append(setOpName);
        stringBuffer.append(TEXT_58);
        stringBuffer.append(selfType);
        stringBuffer.append(TEXT_59);
        stringBuffer.append(referenceType);
        stringBuffer.append(TEXT_60);
        stringBuffer.append(varName);
        stringBuffer.append(TEXT_61);
        stringBuffer.append(unsetOpName);
        stringBuffer.append(TEXT_62);
        stringBuffer.append(selfType);
        stringBuffer.append(TEXT_63);

                    }
                    else {
                        String owningOpClassName = UGenUtil.getObjectOpClassName(
                            feature.getContainingClass()
                        );

        stringBuffer.append(TEXT_64);
        stringBuffer.append(setOpName);
        stringBuffer.append(TEXT_65);
        stringBuffer.append(selfType);
        stringBuffer.append(TEXT_66);
        stringBuffer.append(referenceType);
        stringBuffer.append(TEXT_67);
        stringBuffer.append(varName);
        stringBuffer.append(TEXT_68);
        stringBuffer.append(owningOpClassName);
        stringBuffer.append(TEXT_69);
        stringBuffer.append(setOpName);
        stringBuffer.append(TEXT_70);
        stringBuffer.append(varName);
        stringBuffer.append(TEXT_71);
        stringBuffer.append(unsetOpName);
        stringBuffer.append(TEXT_72);
        stringBuffer.append(selfType);
        stringBuffer.append(TEXT_73);
        stringBuffer.append(owningOpClassName);
        stringBuffer.append(TEXT_74);
        stringBuffer.append(unsetOpName);
        stringBuffer.append(TEXT_75);

                    }
                }
            }
        }
    }

    for (UOperation operation : object.getAllOperations()) {
        if (operation.isProvided()) {
            continue;
        }
        
        boolean retunAble = operation.getType() != UModel.UVOID;

        if (object == operation.getContainingClassifier()) {
            String signature = UGenUtil.createOperationSignatureForDelegating(
                object, operation, importBuilder, true, false, "", "public"
            );

        stringBuffer.append(TEXT_76);
        stringBuffer.append(signature);
        stringBuffer.append(TEXT_77);

        }
        else {
            String owningOpClassName = UGenUtil.getObjectOpClassName(
                operation.getContainingClassifier()
            );

            String signature = UGenUtil.createOperationSignatureForDelegating(
                object, operation, importBuilder, false, false, "", "public"
            );

        stringBuffer.append(TEXT_78);
        stringBuffer.append(signature);
        stringBuffer.append(TEXT_79);
        stringBuffer.append(retunAble ? "return " : "");
        stringBuffer.append(owningOpClassName);
        stringBuffer.append(TEXT_80);
        stringBuffer.append(operation.getName());
        stringBuffer.append(TEXT_81);
        stringBuffer.append(UGenUtil.createParameterNameListForDelegating("self", operation));
        stringBuffer.append(TEXT_82);

        }
    }

        stringBuffer.append(TEXT_83);

    insertImport(stringBuffer, importBuilder, opStubClassName);

        stringBuffer.append(TEXT_84);

        return stringBuffer.toString();
    }

    // ---------------------------------------------------------------------------------------
    // ---------------------------------------------------------------------------------------

}
